package com.sk.weichat.util;

import android.graphics.Paint;
import android.graphics.Point;
import android.support.v4.widget.TextViewCompat;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class TextViewUtil {

    private static final String ELLIPSIS_NORMAL = "\u2026"; // HORIZONTAL ELLIPSIS (…)

    public static void ellipsize(TextView textView, String content) {
        TextUtils.TruncateAt ellipsize = textView.getEllipsize();
        if (ellipsize != TextUtils.TruncateAt.START && ellipsize != TextUtils.TruncateAt.MIDDLE) { // 只处理start和middle的截断
            textView.setText(content);
            return;
        }

        int maxLine = TextViewCompat.getMaxLines(textView);
        textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        int availableWidth = textView.getMeasuredWidth() - textView.getPaddingLeft() - textView.getPaddingRight();
        if (maxLine < 2) { // 单行，或没做行数限制
            textView.setText(content);
        } else {
            List<Point> linesStart = getLineStartAndEnd(textView.getPaint(), content, availableWidth);
            if (linesStart.size() <= maxLine) { // 行数没有超过限制，不做处理
                textView.setText(content);
                return;
            }

            if (ellipsize == TextUtils.TruncateAt.START) {
                int start = linesStart.get(linesStart.size() - maxLine).x;
                start = Math.max(start + ELLIPSIS_NORMAL.length(), 0);
                String substring = content.substring(start);
                // 裁剪文字，直到在行数范围内可显示
                while (getLayout(textView.getPaint(), ELLIPSIS_NORMAL + substring, availableWidth).getLineCount() > maxLine) {
                    int firstSpace = substring.indexOf(' '); // 空白字符
                    if (firstSpace == -1) {
                        substring = substring.substring(1);
                    } else {
                        substring = substring.substring(firstSpace + 1);
                    }
                }
                textView.setText(ELLIPSIS_NORMAL + substring);
            } else { // middle
                int middleLineStart = (maxLine - 1) / 2;
                Point point = linesStart.get(middleLineStart);
                int startEllipsize = point.y - ELLIPSIS_NORMAL.length();// 在中间行的末尾追加省略号
                final String substringStart = content.substring(0, startEllipsize); // 省略号前面的文字

                int middleLineEnd = linesStart.size() - (maxLine - (maxLine - 1) / 2 - 1);
                Point pointEnd = linesStart.get(middleLineEnd);
                String substringEnd = content.substring(pointEnd.x);
                // 裁剪省略号后面的文字，直到整体在行数范围内可显示
                while (getLayout(textView.getPaint(), substringStart + ELLIPSIS_NORMAL + substringEnd, availableWidth).getLineCount() > maxLine) {
                    int firstSpace = substringEnd.indexOf(' '); // 空白字符
                    if (firstSpace == -1) {
                        substringEnd = substringEnd.substring(1);
                    } else {
                        substringEnd = substringEnd.substring(firstSpace + 1);
                    }
                }
                textView.setText(substringStart + ELLIPSIS_NORMAL + substringEnd);
            }
        }
    }

    /**
     * 计算每一行的开始字符位置和结束字符位置
     *
     * @return List.size()为总行数．point.x 为当前行的开始字符位置， point.y 为当前行的结束字符位置
     */
    private static List<Point> getLineStartAndEnd(TextPaint tp, CharSequence cs, int lineWidth) {
        // StaticLayout是android中处理文字换行的一个工具类，StaticLayout已经实现了文本绘制换行处理
        StaticLayout layout = new StaticLayout(cs, tp, lineWidth, Layout.Alignment.ALIGN_NORMAL,
                1.0f, 0.0f, true);
        int count = layout.getLineCount();
        List<Point> list = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            list.add(new Point(layout.getLineStart(i), layout.getLineEnd(i)));
        }
        return list;
    }

    private static Layout getLayout(TextPaint tp, CharSequence cs, int lineWidth) {
        StaticLayout layout = new StaticLayout(cs, tp, lineWidth, Layout.Alignment.ALIGN_NORMAL,
                1.0f, 0.0f, true);
        return layout;
    }

    /**
     * 字符串显示到textView, textView maxLines=2
     * 如果字符串太长显示不下，则用省略号代替
     * 省略号的位置在第一行末尾
     *
     * @param textView 显示字符串的view
     * @param str      要显示的字符串
     * @param width    显示字符串的view的宽
     * @return 处理后带省略号的字符串
     */
    public static String ellipsizeString(TextView textView, String str, int width) {
        Paint paint = textView.getPaint();
        //文字总宽小于2倍的view宽，说明小于2行，直接返回
        if (paint.measureText(str) < 2 * width) {
            return str;
        }

        //存储显示到view的每行文字
        List<String> list = new ArrayList<>();

        int len = 0;
        int start, end = 0;

        while (len < str.length()) {
            len += end;
            int count = paint.breakText(str, end, str.length(), true, width, null);
            start = end;
            end = end + count;
            list.add(str.substring(start, end));
        }

        //第一行文字末尾三个字符替换成省略号
        String line1 = list.get(0);
        line1 = line1.substring(0, line1.length() - 3) + ELLIPSIS_NORMAL;

        //最后一行半的文字从末尾向前截取一行文字
        String endLine = list.get(list.size() - 1);
        int endLineWidth = (int) paint.measureText(endLine);
        String minorEndLine = list.get(list.size() - 2);
        int minorCuteCount = paint.breakText(minorEndLine, 0, minorEndLine.length(), true, endLineWidth, null);
        String line2 = minorEndLine.substring(minorCuteCount, minorEndLine.length()) + endLine;

        return line1 + line2;
    }

    public static int measureViewWidth( View view) {
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        if (lp == null) {
            lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT
            );
        }
        int widthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
        int lpHeight = lp.height;
        int heightSpec;
        if (lpHeight > 0) {
            heightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, View.MeasureSpec.EXACTLY);
        } else {
            heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        }
        view.measure(widthSpec, heightSpec);
        int width = view.getMeasuredWidth();
        return width;
    }
}
